package com.larrylague.preloader
{
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.filters.DropShadowFilter;
	
	public class SpinningPreloader extends Sprite
	{
		public static const SEGMENTED:String = "segmented";
		public static const SOLID:String = "solid";
		
		private var _numSlices:int = 13;
		private var _type:String;
		private var _radius:int;
		private var _fillColor:uint;
		private var _followCursor:Boolean = false;
		private var _hasShadow:Boolean = false;
		
		
		public function SpinningPreloader(type:String = "solid", radius:int = 20, color:uint = 0x000000, shadow:Boolean = false)
		{
			if (type != SEGMENTED && type != SOLID) {
				throw new Error("Please choose a preloader type of SpinningPreloader.SEGMENTED or SpinningPreloader.SOLID");
				return;
			}
			
			_type = type;
			_radius = radius;
			_fillColor = color;
			_hasShadow = shadow;
			init();
			addEventListener(Event.REMOVED_FROM_STAGE, kill);
		}
		
		public function start():void
		{
			addEventListener(Event.ENTER_FRAME, update);
		}
		
		public function stop():void
		{
			removeEventListener(Event.ENTER_FRAME, update);
		}
		
		public function set followCursor(value:Boolean):void
		{
			_followCursor = value;
		}
		
		private function init():void
		{
			var i:int;
			var degrees:int = 360 / _numSlices;
			for (i=_numSlices; i>0; --i) {
				var slice:Sprite = _type == SEGMENTED ? getSegmentedSlice() : getSolidSlice();
				addChild(slice);
				var radianAngle:Number = (degrees * i) * Math.PI / 180;
				slice.rotation = -degrees * i;
				slice.x = Math.sin(radianAngle) * _radius;
				slice.y = Math.cos(radianAngle) * _radius;
				slice.alpha = i / _numSlices;
			}
			
			if (_hasShadow) this.filters = [new DropShadowFilter(4, 45, 0, 0.5, 4, 4, 1, 2)];
		}
		
		private function getSegmentedSlice():Sprite
		{
			var sp:Sprite = new Sprite();
			getShape(sp, -2, -8, 4, 2);
			getShape(sp, -2, -3, 4, 2);
			getShape(sp, -2, 2, 4, 2);
			getShape(sp, -2, 6, 4, 2);
			return sp;
		}
		
		private function getSolidSlice():Sprite
		{
			var sp:Sprite = new Sprite();
			getShape(sp, -_radius/8, 0, _radius/4, _radius);
			return sp;
		}
		
		private function getShape(container:Sprite, xPos:Number, yPos:Number, width:Number, height:Number):Shape
		{
			var slice:Shape = new Shape();
			slice.graphics.beginFill(_fillColor);
			slice.graphics.drawRect(0, 0, width, height);
			slice.graphics.endFill();
			slice.x = xPos;
			slice.y = yPos;
			container.addChild(slice);
			return slice;
		}
		
		private function update(event:Event):void
		{
			rotation += 3;
			var i:int;
			for (i=0; i<_numSlices; ++i) {
				var slice:Sprite = Sprite(getChildAt(i));
				slice.alpha -= 0.03;
				if (slice.alpha <= 0) slice.alpha = 1;
			}
			
			if (_followCursor) {
				this.x = stage.mouseX;
				this.y = stage.mouseY;
			}
		}
		
		public function kill(event:Event):void
		{
			removeEventListener(Event.REMOVED_FROM_STAGE, kill);
			if (hasEventListener(Event.ENTER_FRAME)) removeEventListener(Event.ENTER_FRAME, update);
		}
	}
}











